home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-11-11 | 4.2 KB | 193 lines | [TEXT/MMCC] |
- #include "PascalStrings.h"
-
- // ----------------------------------------------------------------------------------------------------------------------
- // String copy routines
-
- // Duff-style unrolled loop. An invention of Tom Duff at Bellcore. This macro generates some pretty unusual code that breaks
- // some compilers. On the other hand it has Dennis Ritchie's blessing as valid C code.
-
- // Of course a simple BlockMove would do, but this is fun. Note that it is only efficient for small amounts of data, since we only
- // move one byte at a time. Longword moves would be more efficient.
-
- #define LOOP8(n, s) { \
- register long __i; \
- __i = n >> 3; \
- switch(n & 7) { \
- do { \
- s; \
- case 7: s; \
- case 6: s; \
- case 5: s; \
- case 4: s; \
- case 3: s; \
- case 2: s; \
- case 1: s; \
- case 0: ; \
- } while (__i--); \
- } \
- }
-
- static void DuffBlockMove (const unsigned char *source, unsigned char *dest, long n)
- {
- #define MoveOneByte *(dest++) = *(source++)
- LOOP8(n, MoveOneByte);
- }
-
- void StringCopy (const unsigned char *source, StringPtr dest)
- {
- register Byte n = *source + 1;
- #define MoveOneByte *(dest++) = *(source++)
- LOOP8(n, MoveOneByte);
- }
-
- void String2Text (const unsigned char *source, StringPtr dest)
- {
- register Byte n = *(source++);
- #define MoveOneByte *(dest++) = *(source++)
- LOOP8(n, MoveOneByte);
- }
-
- // ----------------------------------------------------------------------------------------------------------------------
- // Implementation of the PascalString class.
-
- PascalString::PascalString (const Str255& source)
- {
- StringCopy(source, S);
- }
-
- PascalString::PascalString ()
- {
- S[0] = 0;
- }
-
- PascalString& PascalString::operator= (const PascalString& source)
- {
- StringCopy(source.S, S);
- return *this;
- }
-
- PascalString& PascalString::operator= (const Str255& source)
- {
- StringCopy(source, S);
- return *this;
- }
-
- PascalString::PascalString (const PascalString& source)
- {
- StringCopy(source.S, S);
- }
-
- PascalString operator+ (const PascalString& p1, const PascalString& p2)
- {
- PascalString result;
- unsigned char len1 = p1.S[0];
- unsigned char len2 = p2.S[0];
-
- result = p1;
- if (len1 + len2 <= 255) { // Beware of overflows!
- DuffBlockMove(p2.S + 1, result.S + len1 + 1, len2);
- result.S[0] = len1 + len2;
- }
- else {
- DuffBlockMove(p2.S + 1, result.S + len1 + 1, 255 - len1);
- result.S[0] = 255;
- }
-
- return result;
- }
-
- PascalString& PascalString::operator+= (const PascalString& source)
- {
- unsigned char len1 = S[0];
- unsigned char len2 = source.S[0];
-
- if (len1 + len2 <= 255) {
- DuffBlockMove(source.S + 1, S + len1 + 1, len2);
- S[0] += len2;
- }
- else {
- DuffBlockMove(source.S + 1, S + len1 + 1, 255 - len1);
- S[0] = 255;
- }
-
- return *this;
- }
-
- PascalString& PascalString::operator+= (const Str255& source)
- {
- unsigned char len1 = S[0];
- unsigned char len2 = source[0];
-
- if (len1 + len2 <= 255) {
- DuffBlockMove(source + 1, S + len1 + 1, len2);
- S[0] += len2;
- }
- else {
- DuffBlockMove(source + 1, S + len1 + 1, 255 - len1);
- S[0] = 255;
- }
-
- return *this;
- }
-
- PascalString::PascalString (OSType source)
- {
- Ptr p = (Ptr) &source;
-
- S[0] = 4;
- S[1] = p[0]; S[2] = p[1]; S[3] = p[2]; S[4] = p[3];
- }
-
- PascalString::operator OSType ()
- {
- OSType result;
- Ptr p = (Ptr) &result;
-
- p[0] = S[0] > 0 ? S[1] : ' ';
- p[1] = S[0] > 1 ? S[2] : ' ';
- p[2] = S[0] > 2 ? S[3] : ' ';
- p[3] = S[0] > 3 ? S[4] : ' ';
- return result;
- }
-
- PascalString::PascalString (long source)
- {
- NumToString(source, S);
- }
-
- PascalString::operator long ()
- {
- long result;
-
- StringToNum(S, &result);
- return result;
- }
-
- // PStringCmp works like IUCompString : it returns -1 if S1 < S2, 0 if S1 == S2 and +1 if S1 > S2.
- // PStringCmp has two advantages over IUCompString: first, it is probably much faster, although I didn't do any timing tests.
- // Second, it defines an ordering relation, i.e. it verifies PStringCmp(S1, S2) == -PStringCmp(S2, S1). IUCompString doesn't
- // (is it a bug or a feature?)
-
- short PStringCmp (StringPtr S1, StringPtr S2)
- {
- Byte len1 = S1[0];
- Byte len2 = S2[0];
- Byte i = 1;
-
- while (true) {
- if (i > len1 && i > len2)
- return 0;
- else if (i > len1)
- return -1;
- else if (i > len2)
- return 1;
- else {
- if (S1[i] < S2[i])
- return -1;
- else if (S1[i] > S2[i])
- return 1;
- else
- i++;
- }
- }
- }